#include "Holiday.h"

Holiday::Holiday()
{
}

Holiday::~Holiday()
{
}

void Holiday::link(DataStore* i, Mailbox* j)
{
    ds = i;
    mb = j;
}

void Holiday::createPackage()
{
    srand(time(NULL));

    cout << "Creating Package" << endl
            << "----------------" << endl;

    int code;
    string destination;
    holidayType holType;
    int HMid;


    int checkCode;
    do
    {
        code = rand() % 99 + 1;
        checkCode = ds->findHolCode(code);

    }
    while (checkCode != 0);

    cout << "Package Code: "
            << code
            << endl;

    cout << "Destination: ";
    getline(cin, destination, '\n');

    int opt;
    // Note that in enum and database, the reference is 
    // 0, 1, 2, 3 respectively.

    do
    {
        cout << "Holiday Type: " << endl
                << "\t1. The Small Adventure (3 days break)" << endl
                << "\t2. The Triers Adventure (7 days break)" << endl
                << "\t3. The Great Adventure (14 days break)" << endl
                << "\t4. The Really Big Adventure (28 days break)" << endl
                << "Option: ";
        cin >> opt;
        cin.clear();
        cin.ignore(INT_MAX, '\n');

        switch (opt)
        {
        case 1:
        case 2:
        case 3:
        case 4: holType = static_cast<holidayType> (opt - 1);
            break;
        default: opt = 0;
        }
        cout << endl;
    }
    while (opt == 0);


    cout << "Holiday Manager List: " << endl << endl;
    printHMdetails();


    int checkId;
    int countHM;
    do
    {
        cout << "Assign Holiday Manager Id: ";
        cin >> HMid;
        cin.clear();
        cin.ignore(INT_MAX, '\n');

        checkId = ds->findUserID(HMid);
        if (checkId == 0)
            cout << "Id not found. Please assign a valid ID"
                << endl;

        countHM = countHMdest(HMid);
        if (countHM == 5)
            cout << "This manager already has 5 locations. "
                << "Please assign it to another manager."
                << endl;

    }
    while (checkId == 0 || countHM == 5);

    holStruct temp;
    temp.code = code;
    temp.destination = destination;
    temp.type = holType;
    temp.managerID = HMid;

    ds->holidays.push_back(temp);

    stringstream mailer;
    mailer << "New Holiday Package to " << temp.destination
            << " which is a " << ds->holidayString(temp.type) << " is now available!";
    string output = mailer.str();

    mb->sendMail(output);

    cout << endl;
}

void Holiday::deletePackage()
{
    cout << "Deleting Package" << endl
            << "----------------" << endl;

    printAllpackages();

    int id;
    int checkId;
    do
    {
        cout << "Enter package ID: ";
        cin >> id;
        cin.clear();
        cin.ignore(INT_MAX, '\n');

        checkId = ds->findHolCode(id);

        if (checkId == 0)
            cout << "Invalid package ID."
                << endl;

    }
    while (checkId == 0);

    int IDposition = ds->findHolCode(id) - 1;

    ds->removeHolidays(IDposition);
    cout << endl;

    cout << "Clients' info for this deleted package are: "
            << endl << endl;

    cout << left << setw(35) << "Client Name"
            << left << setw(60) << "Client Address"
            << endl;

    cout << setw(95) << setfill('-') << "-" << endl;
    cout << setfill(' ');

    printClientAdd(id);

    cout << endl;

}

void Holiday::editPackage()
{
    cout << "Updating Package" << endl
            << "----------------" << endl;

    printAllpackages();

    int id;
    int checkId;
    do
    {
        cout << "Enter package ID: ";
        cin >> id;
        cin.clear();
        cin.ignore(INT_MAX, '\n');

        checkId = ds->findHolCode(id);

        if (checkId == 0)
            cout << "Invalid package ID."
                << endl;

    }
    while (checkId == 0);

    int opt;

    do
    {
        cout << "\t1. Update destination" << endl
                << "\t2. Change holiday type" << endl
                << "\t3. Change holiday manager" << endl
                << "\t4. Quit Editing" << endl;
        cin >> opt;
        cin.clear();
        cin.ignore(INT_MAX, '\n');

        switch (opt)
        {
        case 1: updateDest(id);
            break;
        case 2: updateType(id);
            break;
        case 3: updateManager(id);
            break;
        case 4: break;
        default: opt = 0;
        }
    }
    while (opt != 4);

    cout << endl;

}

void Holiday::listBookers()
{
    cout << "List Bookers For A Package" << endl
            << "--------------------------" << endl;

    printAllpackages();

    int id;
    int checkId;
    do
    {
        cout << "Enter package ID: ";
        cin >> id;
        cin.clear();
        cin.ignore(INT_MAX, '\n');

        checkId = ds->findHolCode(id);

        if (checkId == 0)
            cout << "Invalid package ID."
                << endl;

    }
    while (checkId == 0);

    cout << "Bookers for a package id "
            << id << " are: "
            << endl << endl;

    cout << left << setw(12) << "ReferenceId"
            << left << setw(10) << "ClientId"
            << left << setw(35) << "Name"
            << endl;

    cout << setw(57) << setfill('-') << "-" << endl;
    cout << setfill(' ');

    printCertainBookers(id);

    cout << endl;

}

void Holiday::printCertainBookers(const int packageId)
{
    int size = ds->bookings.size();

    for (int i = 0; i < size; ++i)
    {
        if (ds->bookings[i].code == packageId)
        {
            cout << left << setw(12) << ds->bookings[i].ref
                    << left << setw(10) << ds->bookings[i].clientID
                    << left << setw(35) << ds->bookings[i].name
                    << endl;
        }
    }
}

void Holiday::printClientAdd(const int packageId)
{
    int size = ds->bookings.size();

    for (int i = 0; i < size; ++i)
    {
        if (ds->bookings[i].code == packageId)
        {
            cout << left << setw(35) << ds->bookings[i].name
                    << left << setw(60) << ds->bookings[i].address
                    << endl;
        }
    }
}

void Holiday::printHMdetails()
{
    int sizeAcc = ds->accounts.size();
    int sizeHol = ds->holidays.size();

    for (int i = 0; i < sizeAcc; ++i)
    {
        if ((int) ds->accounts[i].type == 3)
        {
            cout << "Holiday Manager " << ds->accounts[i].ID;

            for (int k = 0; k < sizeHol; ++k)
            {
                if (ds->accounts[i].ID == ds->holidays[k].managerID)
                    cout << endl << " (" << ds->holidays[k].destination << ")";

            }
            cout << endl << endl;
        }
    }
}

int Holiday::countHMdest(const int id)
{
    int count = 0;
    int size = ds->holidays.size();
    for (int i = 0; i < size; i++)
    {
        if (ds->holidays[i].managerID == id)
            ++count;
    }
    return count;
}

void Holiday::printAllpackages()
{
    int size = ds->holidays.size();

    cout << left << setw(12) << "PackageId"
            << left << setw(45) << "Destination"
            << left << setw(15) << "Type"
            << endl;

    cout << setw(72) << setfill('-') << "-" << endl;
    cout << setfill(' ');

    for (int i = 0; i < size; ++i)
    {
        cout << left << setw(12) << ds->holidays[i].code
                << left << setw(45) << ds->holidays[i].destination
                << left << setw(15) << ds->holidayString(ds->holidays[i].type)
                << endl;
    }
}

void Holiday::updateDest(const int id)
{
    int position = ds->findHolCode(id);
    --position;

    string newDest;
    cout << "New destination: ";
    getline(cin, newDest, '\n');

    ds->holidays[position].destination = newDest;
}

void Holiday::updateType(const int id)
{
    int position = ds->findHolCode(id) - 1;

    int newType;

    do
    {
        cout << "Holiday Type: " << endl
                << "\t1. The Small Adventure (3 days break)" << endl
                << "\t2. The Triers Adventure (7 days break)" << endl
                << "\t3. The Great Adventure (14 days break)" << endl
                << "\t4. The Really Big Adventure (28 days break)" << endl
                << "Change holiday type: ";
        cin >> newType;
        cin.clear();
        cin.ignore(INT_MAX, '\n');

        switch (newType)
        {
        case 1:
        case 2:
        case 3:
        case 4: ds->holidays[position].type = (holidayType) (newType - 1);
            break;
        default: newType = 0;
        }
        cout << endl;
    }
    while (newType == 0);
}

void Holiday::updateManager(const int id)
{
    int position = ds->findHolCode(id) - 1;

    int newId;

    cout << "Holiday Manager List: " << endl;
    printHMdetails();

    int checkId;
    int countHM;
    do
    {
        cout << "Change Holiday Manager Id: ";
        cin >> newId;
        cin.clear();
        cin.ignore(INT_MAX, '\n');

        checkId = ds->findUserID(newId);
        if (checkId == 0)
            cout << "Id not found. Please assign a valid ID"
                << endl;

        countHM = countHMdest(newId);
        if (countHM == 5)
            cout << "This manager already has 5 locations. "
                << "Please assign it to another manager."
                << endl;

    }
    while (checkId == 0 || countHM == 5);

    ds->holidays[position].managerID = newId;
}

void Holiday::viewStatistics()
{
    cout << "List of holiday packages:" << endl << endl;
    printAllpackages();
    int id;
    int checkId;
    do
    {
        cout << "Enter package ID: ";
        cin >> id;
        cin.clear();
        cin.ignore(INT_MAX, '\n');

        checkId = ds->findHolCode(id);

        if (checkId == 0)
            cout << "Invalid package ID."
                << endl;

    }
    while (checkId == 0);

    int IDposition = ds->findHolCode(id) - 1;

    cout << endl;

    cout << "Clients' info for this package are: "
            << endl << endl;

    cout << left << setw(35) << "Client Name"
            << left << setw(60) << "Client Address"
            << endl;

    cout << setw(95) << setfill('-') << "-" << endl;
    cout << setfill(' ');

    printClientAdd(id);

    cout << endl;
}